package com.sefer.dragonfly.client.core.thread;

import java.text.MessageFormat;
import java.text.ParseException;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.spi.JobFactory;
import org.quartz.spi.TriggerFiredBundle;

import com.sefer.dragonfly.client.core.consumer.CmJvmConsumer;
import com.sefer.dragonfly.client.core.container.MonitorContainer;
import com.sefer.dragonfly.client.core.domain.CmConsumer;
import com.sefer.dragonfly.client.core.domain.lifecycle.BaseLifecycle;
import com.sefer.dragonfly.client.core.exception.DragonFlyRuntimeException;
import com.sefer.dragonfly.client.tools.RegisterPluginTools;

public class JobScheduler extends BaseLifecycle {
	private static final Logger logger = Logger.getLogger(JobScheduler.class);
	private Scheduler scheduler;

	@Override
	public void init() {
		super.init();
		synchronized (JobScheduler.class) {
			if (scheduler == null) {
				initSchedule();
			}
		}
	}

	@Override
	public void start() {
		super.start();

		try {
			scheduler.start();
		} catch (SchedulerException e) {
			logger.error("Job scheduler start exception. " + e.getMessage(), e);
			throw new RuntimeException("Job scheduler start exception.", e);
		}
	}

	@Override
	public void stop() {
		super.stop();

		try {
			scheduler.standby();
		} catch (SchedulerException e) {
			logger.error("Job scheduler stop exception. " + e.getMessage(), e);
			throw new RuntimeException("Job scheduler start exception.", e);
		}
	}

	@Override
	public void destory() {
		super.destory();

		try {
			scheduler.shutdown();
		} catch (SchedulerException e) {
			logger.error("Job scheduler shutdown exception. " + e.getMessage(),
					e);
			throw new DragonFlyRuntimeException(
					"Job scheduler start exception.", e);
		}
	}

	// ========================

	private void initSchedule() {
		SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
		try {
			scheduler = schedFact.getScheduler();
			scheduler.setJobFactory(new JobFactory() {
				public Job newJob(TriggerFiredBundle bundle, Scheduler scheduler)
						throws SchedulerException {
					JobDetail jobDetail = bundle.getJobDetail();

					Class jobClass = jobDetail.getJobClass();
					try {
						CmConsumer[] plugin = MonitorContainer.getContainer()
								.getPlugin(jobClass);

						if (logger.isDebugEnabled()) {
							logger.error("Problem instantiating class '"
									+ jobDetail.getJobClass().getName() + "'");
						}

						if (plugin == null || plugin.length == 0) {
							return null;
						}

						return (Job) plugin[0];
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
						throw new DragonFlyRuntimeException(
								"New Job exeption.", e);
					}
				}
			});
		} catch (SchedulerException e) {
			throw new RuntimeException("Init JobScheduler Exception: "
					+ e.getMessage(), e);
		}
	}

	public void registerPlugin(CmConsumer plugin) throws Exception {
		if (logger.isDebugEnabled()) {
			logger.debug(MessageFormat.format(
					"Plugin register in job scheduler: {0}",
					RegisterPluginTools.generateKey(plugin)));
		}
		JobDetail jobDetail = JobBuilder
				.newJob(plugin.getClass())
				.withIdentity(
						plugin.getConsumerId() + "_" + plugin.getVersion())
				.build();

		CronTrigger trigger = TriggerBuilder
				.newTrigger()
				.withIdentity(
						plugin.getConsumerId() + "_" + plugin.getVersion())
				.withSchedule(
						CronScheduleBuilder.cronSchedule(plugin
								.getCronExpression())).build();

		try {
			scheduler.scheduleJob(jobDetail, trigger);
		} catch (SchedulerException e) {
			logger.error("Job scheduler exception. " + e.getMessage(), e);
			throw new Exception((MessageFormat.format(
					"Job {0} can't scheduleJob ",
					"Job_" + plugin.getConsumerId())));
		}

	}

	public void unRegisterPlugin(CmConsumer plugin) throws Exception {
		if (!scheduler.deleteJob(new JobKey(generateJobKey(plugin)))) {
			throw new Exception((MessageFormat.format("Job {0} can't delete ",
					"Job_" + plugin.getConsumerId())));
		}
	}

	private String generateJobKey(CmConsumer plugin) {
		return plugin.getConsumerId() + "_" + plugin.getVersion();
	}

	// ====================>>>>>>>>>>>>>>>>>>>

	public static void main(String[] args) throws SchedulerException,
			ParseException {

		JobScheduler schedule = new JobScheduler();

		schedule.init();
		CmJvmConsumer consumer = new CmJvmConsumer();
		consumer.setConsumerId("jvm");
		consumer.setVersion("1.0");
		consumer.setCronExpression("0/1 * * * * ?");

		try {
			schedule.registerPlugin(consumer);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		schedule.start();

		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("standby1.....................");
		schedule.stop();

		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("standby2.....................");
		schedule.stop();

		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("shutdown1.....................");
		schedule.destory();
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("shutdown2.....................");
		schedule.destory();
	}
}
